package com.gzhryc.shared_device.common.payment.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayNormalRefundState;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalRefundNotify;
import com.gzhryc.shared_device.base.enums.ERefundState;
import com.gzhryc.shared_device.common.payment.dao.WXRefundOrderDao;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.dao.db.WXRefundOrder;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

public class WXRefundOrderService {

	static Logger log = Logger.getLogger(WXRefundOrderService.class);

	public static WXRefundOrderService self(Date date) {
		return MultiDBTools.getService(WXRefundOrderService.class, date);
	}

	public static WXRefundOrderService self(String jdbcKey,Date date) {
		return MultiDBTools.getService(jdbcKey, WXRefundOrderService.class, date);
	}

	WXRefundOrderDao dao;

	public WXRefundOrderService(String jdbcKey,Date date) {
		dao = new WXRefundOrderDao(jdbcKey,date);
	}

	public List<WXRefundOrder> findByPayTradeNo(String payTradeNo){
		if(StringTools.isNotBlank(payTradeNo)){
			Conditions conditions = new Conditions(WXRefundOrder.class);
			conditions.and().is("payTradeNo",payTradeNo);

			try {
				return dao.findByCondition(conditions);
			} catch (SQLException e) {
				log.error(e.getMessage(),e);
			}
		}
		return null;
	}

	public Long countByPayTradeNo(String payTradeNo){
		if(StringTools.isNotBlank(payTradeNo)){
			Conditions conditions = new Conditions(WXRefundOrder.class);
			conditions.and().is("payTradeNo",payTradeNo);

			try {
				return dao.count(conditions);
			} catch (SQLException e) {
				log.error(e.getMessage(),e);
			}
		}
		return null;
	}

	public List<WXRefundOrder> findByBusinessTradeNo(String businessTradeNo){
		if(StringTools.isNotBlank(businessTradeNo)){
			Conditions conditions = new Conditions(WXRefundOrder.class);
			conditions.and().is("businessTradeNo",businessTradeNo);

			try {
				return dao.findByCondition(conditions);
			} catch (SQLException e) {
				log.error(e.getMessage(),e);
			}
		}
		return null;
	}

	public WXRefundOrder getByTradeNo(String tradeNo){
		try {
			return dao.getById(tradeNo);
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		}
		return null;
	}

	public WXRefundOrder createRefundOrder(WXPayOrder payOrder, Integer refundMoney, String note) throws LogicException {
		Long total = countByPayTradeNo(payOrder.getTradeNo());
		if(total == null){total = 0L;}
		String tradeNo = payOrder.getTradeNo() + String.format("%02d",total);

		WXRefundOrder refundOrder = new WXRefundOrder();
		refundOrder.setTradeNo(tradeNo);
		refundOrder.setNote(note);
		refundOrder.setPayTradeNo(payOrder.getTradeNo());
		refundOrder.setExternalPayTradeNo(payOrder.getExternalTradeNo());
		refundOrder.setPayMoney(payOrder.getPayMoney());
		refundOrder.setBusinessType(payOrder.getBusinessType());
		refundOrder.setBusinessTypeName(payOrder.getBusinessTypeName());
		refundOrder.setBusinessTradeNo(payOrder.getBusinessTradeNo());
		refundOrder.setAppType(payOrder.getAppType());
		refundOrder.setAppId(payOrder.getAppId());
		refundOrder.setPayerId(payOrder.getPayerId());
		refundOrder.setBusinessAccount(payOrder.getBusinessAccount());
		refundOrder.setTradeType(payOrder.getTradeType());
		refundOrder.setRefundMoney(refundMoney);
		refundOrder.setCreateDate(new Date());

		try {
			if(dao.insert(refundOrder) > 0){
				return refundOrder;
			}
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		}
		return null;
	}

	public boolean toFail(String tradeNo, String errorMsg,String externalContent) {
		if (StringTools.isNotBlank(tradeNo)) {
			WXRefundOrder refundOrder = new WXRefundOrder();
			refundOrder.setTradeNo(tradeNo);
			refundOrder.setRefundStatus(ERefundState.Fail.index());
			refundOrder.setFailNote(errorMsg);
			refundOrder.setExternalContent(externalContent);
			refundOrder.setRefundDate(new Date());

			try {
				if (dao.updateNotNull(refundOrder) > 0) {
					return true;
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}

		}
		return false;
	}

	public boolean toSuccess(String tradeNo,String externalTradeNo,String externalContent){
		if (StringTools.isNotBlank(tradeNo)) {
			WXRefundOrder refundOrder = new WXRefundOrder();
			refundOrder.setTradeNo(tradeNo);
			refundOrder.setRefundStatus(ERefundState.Success.index());
			refundOrder.setExternalTradeNo(externalTradeNo);
			refundOrder.setExternalContent(externalContent);
			refundOrder.setRefundDate(new Date());

			try {
				if (dao.updateNotNull(refundOrder) > 0) {
					return true;
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		return false;
	}

	public WXRefundOrder refundResult(WXPayNormalRefundNotify notify){
		WXRefundOrder refundOrder = getByTradeNo(notify.getOut_refund_no());
		if (refundOrder != null) {
			// 检查金额
			if (!refundOrder.getRefundMoney().equals(notify.getAmount().getRefund())) {
				// throw new LogicException("支付金额不正确");
				log.error("退款金额不正确，回调信息：" + JsonTools.toJson(notify));
			}

			Conditions condition = new Conditions(WXRefundOrder.class);
			condition.and().is("tradeNo", refundOrder.getTradeNo());

			WXRefundOrder updateEntity = new WXRefundOrder();
			updateEntity.setExternalTradeNo(notify.getRefund_id());
			updateEntity.setExternalContent(JsonTools.toJson(notify));
			updateEntity.setRefundMoney(notify.getAmount().getRefund());
			if (EWXPayNormalRefundState.SUCCESS.name().equals(notify.getRefund_status())) {
				updateEntity.setRefundStatus(ERefundState.Success.index());
			} else {
				updateEntity.setRefundStatus(ERefundState.Fail.index());
			}
			updateEntity.setRefundDate(new Date());

			try {
				if (dao.updateNotNull(updateEntity, condition) > 0) {
					refundOrder.setExternalTradeNo(updateEntity.getExternalTradeNo());
					refundOrder.setExternalContent(updateEntity.getExternalContent());
					refundOrder.setRefundMoney(updateEntity.getRefundMoney());
					refundOrder.setRefundStatus(updateEntity.getRefundStatus());
					return refundOrder;
				}
			} catch (SQLException e) {
				log.error("退款解决处理错误，" + e.getMessage(), e);
			}
		} else {
			log.error("提款结果处理未找到退款订单，回调信息：" + JsonTools.toJson(notify));
		}
		return null;
	}
}
